package com.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dto.OrderAddDto;
import com.dto.OrderDto;
import com.dto.OrderSaveDto;
import com.mapper.*;
import com.po.*;
import com.service.OrderService;
import com.vo.PayOrderItemVo;
import com.vo.PayOrderVo;
import com.vo.itemMinuteVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {

    private final OrderDetailMapper orderDetailMapper;

    private final OrderMapper orderMapper;

    private final PayOrderMapper payOrderMapper;

    private final ItemMinuteMapper itemMinuteMapper;

    private final AddressMapper addressMapper;

    private final OrderLogisticsMapper orderLogisticsMapper;

    private final CommentMapper commentMapper;

    private final ItemMapper itemMapper;

    private final RabbitTemplate rabbitTemplate;

    @Override
    @Transactional
    public void add(OrderSaveDto orderSaveDto) {
        List<Long> orderIds = new ArrayList<>();
        List<OrderDto> orderDtolist = orderSaveDto.getOrderDtolist();
        Integer price = 0;
        for (OrderDto orderDto : orderDtolist) {
            List<OrderAddDto> orderAddDtoList = orderDto.getOrderAddDtoList();
            List<Long> ids = new ArrayList<>();
            for (OrderAddDto orderAddDto : orderAddDtoList) {
                price += orderAddDto.getPrice();
                ids.add(orderAddDto.getId());
            }
            //存入order表
            Orders order = new Orders();
            BeanUtil.copyProperties(orderDto,order);
            order.setTotalFee(price);
            order.setPaymentType(3);
            order.setUserId(StpUtil.getLoginIdAsLong());
            order.setStatus(1);
            order.setCreateTime(LocalDateTime.now());
            log.info("order:{}",order);
            save(order);
            orderIds.add(order.getId());
            //存入orderdetail表
            OrderDetail orderDetail = new OrderDetail();
            BeanUtil.copyProperties(orderDto,orderDetail);
            List<String> collect = ids.stream().map(String::valueOf).collect(Collectors.toList());
            String id = String.join(",", collect);
            orderDetail.setPrice(price);
            orderDetail.setItemMinuteId(id);
            orderDetail.setOrderId(order.getId());
            orderDetail.setCreateTime(LocalDateTime.now());
            orderDetailMapper.insert(orderDetail);
        }
        //提交支付单，此时未支付
        List<String> collect = orderIds.stream().map(String::valueOf).collect(Collectors.toList());
        String bizOrderNo = String.join(",", collect);
        PayOrder payOrder = new PayOrder();
        payOrder.setBizOrderNo(bizOrderNo);
        payOrder.setAmount(price);
        payOrder.setBizUserId(StpUtil.getLoginIdAsLong());
        payOrder.setPayType(5);
        payOrder.setStatus(1);
        LocalDateTime now = LocalDateTime.now();
        payOrder.setCreateTime(now);
        payOrder.setCreater(StpUtil.getLoginIdAsLong());
        payOrder.setPayOverTime(now.plusMinutes(15));
        payOrderMapper.insert(payOrder);
        // 1.创建消息
        Long message = payOrder.getId();
        // 2.发送消息，利用消息后置处理器添加消息头
        rabbitTemplate.convertAndSend("delay.direct", "delay", message, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                // 添加延迟消息属性
                message.getMessageProperties().setHeader("x-delay",150000);
                return message;
            }
        });
    }

    @Override
    @Transactional
    public void again(Long id) {
        Orders order = orderMapper.selectById(id);
        order.setId(null);
        order.setStatus(1);
        order.setCreateTime(LocalDateTime.now());
        save(order);
        LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<OrderDetail>()
                .eq(OrderDetail::getOrderId, id);
        OrderDetail orderDetail = orderDetailMapper.selectOne(wrapper);
        orderDetail.setId(null);
        orderDetail.setOrderId(order.getId());
        orderDetail.setCreateTime(LocalDateTime.now());
        orderDetailMapper.insert(orderDetail);
        //提交支付单，此时未支付
        PayOrder payOrder = new PayOrder();
        payOrder.setBizOrderNo(String.valueOf(order.getId()));
        payOrder.setAmount(orderDetail.getPrice());
        payOrder.setBizUserId(StpUtil.getLoginIdAsLong());
        payOrder.setPayType(5);
        payOrder.setStatus(1);
        LocalDateTime now = LocalDateTime.now();
        payOrder.setCreateTime(now);
        payOrder.setCreater(StpUtil.getLoginIdAsLong());
        payOrder.setPayOverTime(now.plusMinutes(15));
        payOrderMapper.insert(payOrder);

    }

    @Override
    public void delete(Long id) {
        LambdaUpdateWrapper<Orders> wrapper = new LambdaUpdateWrapper<Orders>()
                .set(Orders::getStatus, 5)
                .set(Orders::getCloseTime, LocalDateTime.now())
                .set(Orders::getUpdateTime, LocalDateTime.now())
                .in(Orders::getId, id);
        update(null,wrapper);
        //软删除pay
        LambdaUpdateWrapper<PayOrder> updateWrapper = new LambdaUpdateWrapper<PayOrder>()
                .set(PayOrder::getStatus, 2)
                .set(PayOrder::getPayCancelTime, LocalDateTime.now())
                .set(PayOrder::getUpdateTime, LocalDateTime.now())
                .set(PayOrder::getUpdater, StpUtil.getLoginIdAsLong())
                .set(PayOrder::getIsDelete, 1)
                .in(PayOrder::getBizOrderNo, id);
        payOrderMapper.update(null,updateWrapper);
    }

    @Override
    public List<PayOrderVo> ilist(Integer status) {
        //根据订单状态转化为支付状态
        int paystatus = 1;
        if (status > 1){
            if (status == 5){
                paystatus = 2;
            }else {
                paystatus = 3;
            }
        }
        //构建支付单查询条件
        LambdaQueryWrapper<PayOrder> queryWrapper = new LambdaQueryWrapper<PayOrder>()
                .eq(status != 0,PayOrder::getStatus, paystatus)
                .eq(PayOrder::getBizUserId,StpUtil.getLoginIdAsLong());
        //拿到对应状态的支付数据
        List<PayOrder> payOrders = payOrderMapper.selectList(queryWrapper);
        List<PayOrderVo> payOrderVoList = new ArrayList<>();
        //为每个支付单赋值返回
        payOrders.forEach(payOrder -> {
            //拿到支付单包含的订单id，可能包含多个订单id
            String bizOrderNo = payOrder.getBizOrderNo();
            List<String> list= Arrays.asList(bizOrderNo.split(","));
            List<Long> ids = list.stream().map(Long::parseLong).collect(Collectors.toList());
            PayOrderVo payOrderVo = new PayOrderVo();
            BeanUtil.copyProperties(payOrder,payOrderVo);
            List<Orders> orders = new ArrayList<>();
            //如果查询未支付需要返回超时时间
            if (payOrder.getStatus() == 1){
                payOrderVo.setOverTime(payOrder.getPayOverTime());
            }
            //将支付单包含的订单详细全部拿到
            for (Long id : ids) {
                LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<Orders>()
                        .eq(Orders::getId, id);
                Orders order = getOne(wrapper);
                orders.add(order);
            }
            List<PayOrderItemVo> payOrderItemVoList = new ArrayList<>();
            //将每个订单必要的信息返回
            orders.forEach(order -> {
                PayOrderItemVo payOrderItemVo = new PayOrderItemVo();
                payOrderItemVo.setUserId(order.getUserId());
                //拿到订单表对应的订单详情表
                LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<OrderDetail>()
                        .eq(OrderDetail::getOrderId, order.getId());
                OrderDetail orderDetail = orderDetailMapper.selectOne(wrapper);
                //从订单详情表获取必要的订单信息
                BeanUtil.copyProperties(orderDetail,payOrderItemVo);
                payOrderItemVo.setItemPrice(order.getItemPrice());
                payOrderItemVo.setItemId(orderDetail.getItemId());
                payOrderItemVo.setStatus(status);
                //从订单详情表拿到该订单包含的单品id
                String itemMinuteId = orderDetail.getItemMinuteId();
                List<String> list1= Arrays.asList(itemMinuteId.split(","));
                List<Long> ids2 = list1.stream().map(Long::parseLong).collect(Collectors.toList());
                List<itemMinuteVo> itemMinuteVoList = new ArrayList<>();
                //查询对应的单品并且将信息返回
                ids2.forEach(id -> {
                    ItemMinute itemMinute = itemMinuteMapper.selectById(id);
                    itemMinuteVo itemMinuteVo = new itemMinuteVo();
                    BeanUtil.copyProperties(itemMinute,itemMinuteVo);
                    itemMinuteVoList.add(itemMinuteVo);
                });
                payOrderItemVo.setItemMinuteVoList(itemMinuteVoList);
                payOrderItemVoList.add(payOrderItemVo);

            });
            payOrderVo.setPayOrderItemVoList(payOrderItemVoList);
            payOrderVoList.add(payOrderVo);
        });
        return payOrderVoList;
    }

    @Override
    public List<PayOrderItemVo> get(String strId) {
        List<String> list= Arrays.asList(strId.split(","));
        List<Long> ids = list.stream().map(Long::parseLong).collect(Collectors.toList());
        List<PayOrderItemVo> payOrderItemVoList = new ArrayList<>();
        ids.forEach(id -> {
            Orders orders = getById(id);
            LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<OrderDetail>()
                    .eq(OrderDetail::getOrderId, id);
            OrderDetail orderDetail = orderDetailMapper.selectOne(wrapper);
            PayOrderItemVo payOrderItemVo = new PayOrderItemVo();
            BeanUtil.copyProperties(orderDetail,payOrderItemVo);
            BeanUtil.copyProperties(orders,payOrderItemVo);
            //从订单详情表拿到该订单包含的单品id
            String itemMinuteId = orderDetail.getItemMinuteId();
            List<String> list1= Arrays.asList(itemMinuteId.split(","));
            List<Long> ids2 = list1.stream().map(Long::parseLong).collect(Collectors.toList());
            List<itemMinuteVo> itemMinuteVoList = new ArrayList<>();
            //查询对应的单品并且将信息返回
            ids2.forEach(id1 -> {
                ItemMinute itemMinute = itemMinuteMapper.selectById(id1);
                itemMinuteVo itemMinuteVo = new itemMinuteVo();
                BeanUtil.copyProperties(itemMinute,itemMinuteVo);
                itemMinuteVoList.add(itemMinuteVo);
            });
            payOrderItemVo.setItemMinuteVoList(itemMinuteVoList);
            payOrderItemVoList.add(payOrderItemVo);
        });
        return payOrderItemVoList;
    }

    @Override
    @Transactional
    public void shipments(Long id) {
        System.out.println("id = " + id);
        Orders orders = getById(id);
        LambdaQueryWrapper<Address> eq = new LambdaQueryWrapper<Address>()
                .eq(Address::getUserId, orders.getUserId())
                .eq(Address::getIsDefault, 1);
        Address address = addressMapper.selectOne(eq);
        OrderLogistics orderLogistics = new OrderLogistics();
        BeanUtil.copyProperties(address,orderLogistics);
        orderLogistics.setOrderId(id);
        orderLogistics.setLogisticsCompany("顺丰");
        orderLogistics.setLogisticsNumber(StpUtil.getLoginIdAsString());
        LocalDateTime now = LocalDateTime.now();
        orderLogistics.setCreateTime(now);
        orderLogisticsMapper.insert(orderLogistics);
        LambdaUpdateWrapper<Orders> in = new LambdaUpdateWrapper<Orders>()
                .set(Orders::getStatus, 3)
                .set(Orders::getConsignTime, now)
                .set(Orders::getUpdateTime, now)
                .in(Orders::getId, id);
        update(null,in);

    }

    @Override
    @Transactional
    public void comment(Long id,String content,String finalFilePath) {
        LambdaUpdateWrapper<Orders> in = new LambdaUpdateWrapper<Orders>()
                .set(Orders::getCommentTime, LocalDateTime.now())
                .set(Orders::getUpdateTime, LocalDateTime.now())
                .set(Orders::getStatus,6)
                .in(Orders::getId, id);
        update(null,in);
        LambdaQueryWrapper<OrderDetail> eq = new LambdaQueryWrapper<OrderDetail>()
                .eq(OrderDetail::getOrderId, id);
        OrderDetail orderDetail = orderDetailMapper.selectOne(eq);
        Comment comment = new Comment();
        comment.setItemId(orderDetail.getItemId());
        comment.setImage(finalFilePath);
        comment.setCreateTime(LocalDateTime.now());
        comment.setUserId(StpUtil.getLoginIdAsLong());
        comment.setContent(content);
        commentMapper.insert(comment);
        Item item = itemMapper.selectById(orderDetail.getItemId());
        LambdaUpdateWrapper<Item> wrapper = new LambdaUpdateWrapper<Item>()
                .set(Item::getCommentCount, item.getCommentCount() + 1)
                .set(Item::getUpdateTime, LocalDateTime.now())
                .in(Item::getId, orderDetail.getItemId());
        itemMapper.update(null,wrapper);
    }
}
